#include "preHeader.h"
#include "MapServerProxy.h"
#include "MapServerSession.h"
#include "MapServerMgr.h"
#include "Game/TeleportMgr.h"
#include "Game/Account.h"

MapServerProxy::MapServerProxy(MapServerSession* pSession)
: m_pSession(pSession)
{
}

MapServerProxy::~MapServerProxy()
{
}

void MapServerProxy::AddCharacter(Character* pChar)
{
	if (!sTeleportMgr.HasPlayerLoadInfo(pChar->guid)) {
		WLOG("AddCharacter: Can't find player[%u] load info.",
			pChar->guid.UID);
		return;
	}

	m_players.emplace(pChar->guid, pChar);
	sTeleportMgr.OnEnterToTargetMS(this, pChar);
	PushPlayer2GateServer(pChar, true);
}

void MapServerProxy::RemoveCharacter(Character* pChar)
{
	m_players.erase(pChar->guid);
	sTeleportMgr.OnLeaveFromSourceMS(this, pChar);
	PushPlayer2GateServer(pChar, false);
}

Character* MapServerProxy::GetCharacter(ObjGUID guid) const
{
	auto itr = m_players.find((guid.SID = 0, guid));
	return itr != m_players.end() ? itr->second : NULL;
}

void MapServerProxy::SendPacket(const INetPacket& pck) const
{
	m_pSession->PushSendPacket(pck);
}

void MapServerProxy::SendPacket(const INetPacket& pck, const INetPacket& data) const
{
	m_pSession->PushSendPacket(pck, data);
}

void MapServerProxy::TransInstancePacket(InstGUID guid, const INetPacket& pck) const
{
	NetPacket trans(GS_TRANS_INSTANCE_PACKET);
	trans << guid;
	m_pSession->PushSendPacket(trans, pck);
}

void MapServerProxy::TransPlayerPacket(ObjGUID guid, const INetPacket& pck) const
{
	NetPacket trans(GS_TRANS_PLAYER_PACKET);
	trans << guid;
	m_pSession->PushSendPacket(trans, pck);
}

void MapServerProxy::TransRPCInvoke2InstancePacket(InstGUID guid, const INetPacket& pck,
	const std::function<void(INetStream&, int32, bool)>& cb,
	AsyncTaskOwner* owner, time_t timeout) const
{
	NetPacket trans(GS_TRANS_INSTANCE_PACKET);
	trans << guid;
	m_pSession->RPCTransInvoke(trans, pck, cb, owner, timeout);
}

void MapServerProxy::TransRPCInvoke2PlayerPacket(ObjGUID guid, const INetPacket& pck,
	const std::function<void(INetStream&, int32, bool)>& cb,
	AsyncTaskOwner* owner, time_t timeout) const
{
	NetPacket trans(GS_TRANS_PLAYER_PACKET);
	trans << guid;
	m_pSession->RPCTransInvoke(trans, pck, cb, owner, timeout);
}

void MapServerProxy::TransRPCReply2InstancePacket(InstGUID guid, const INetPacket& pck,
	uint64 sn, int32 err, bool eof) const
{
	NetPacket trans(GS_TRANS_INSTANCE_PACKET);
	trans << guid;
	m_pSession->RPCTransReply(trans, pck, sn, err, eof);
}

void MapServerProxy::TransRPCReply2PlayerPacket(ObjGUID guid, const INetPacket& pck,
	uint64 sn, int32 err, bool eof) const
{
	NetPacket trans(GS_TRANS_PLAYER_PACKET);
	trans << guid;
	m_pSession->RPCTransReply(trans, pck, sn, err, eof);
}

void MapServerProxy::SendPacket2CrossServer(const INetPacket& pck) const
{
	NetPacket trans(GS_TRANS_CROSS_SERVER_PACKET);
	m_pSession->PushSendPacket(trans, pck);
}

void MapServerProxy::SendPacket2CrossServer(
	const INetPacket& pck, const std::string_view& data) const
{
	NetPacket trans(GS_TRANS_CROSS_SERVER_PACKET);
	const INetPacket *pcks[] = {&trans, &pck};
	m_pSession->PushSendPacket(pcks, ARRAY_SIZE(pcks), &data, 1);
}

void MapServerProxy::PushPlayer2GateServer(Character* pChar, bool isEnter) const
{
	auto pAccount = pChar->GetAccount();
	if (pAccount != NULL) {
		NetPacket pack(SGG_PUSH_PLAYER);
		pack << pAccount->sn << (isEnter ? m_pSession->sn() : 0);
		pAccount->SendPacket2GateServer(pack);
	}
}
